// backend/controllers/articleController.js
const fs = require('fs/promises');
const path = require('path');
const { v4: uuidv4 } = require('uuid');
const llmService = require('../services/llmService');
const imageService = require('../services/imageService');
const wechatService = require('../services/wechatService');
const logger = require('../services/logger');

const dbPath = path.join(__dirname, '..', 'data', 'db.json');

// --- 数据库读写辅助函数 (保持不变) ---
async function readDb() {
  try {
    await fs.access(dbPath);
    const data = await fs.readFile(dbPath, 'utf8');
    return JSON.parse(data);
  } catch (error) {
    if (error.code === 'ENOENT') {
      const initialData = { articles: [], knowledgeBase: [] };
      await fs.writeFile(dbPath, JSON.stringify(initialData, null, 2), 'utf8');
      return initialData;
    }
    throw error;
  }
}
async function writeDb(data) {
  await fs.writeFile(dbPath, JSON.stringify(data, null, 2), 'utf8');
}

// --- 文章处理与保存辅助函数 (保持不变) ---
async function _processAndSaveArticle(topic, markdownContentWithPlaceholders) {
    const generationLog = {
      timestamp: new Date().toISOString(),
      topic: topic,
      llmRawResponse: markdownContentWithPlaceholders,
      images: [],
      finalMarkdown: '',
    };
    
      logger.info("解析图片占位符...");
    const imagePlaceholderRegex = /\[IMAGE:(.*?)\]/g;
    const imagePrompts = [];
    let match;
    while ((match = imagePlaceholderRegex.exec(markdownContentWithPlaceholders)) !== null) {
        imagePrompts.push(match[1].trim());
    }

    let finalMarkdownContent = markdownContentWithPlaceholders;
    let coverImageLocalPath = null; // 默认封面图为null

    if (imagePrompts.length > 0) {
        logger.info(`找到了 ${imagePrompts.length} 个图片指令，正在并行生成和下载...`);
        
        const externalImageUrls = imagePrompts.map(prompt => imageService.getImageUrl(prompt));
        const downloadPromises = externalImageUrls.map(url => imageService.downloadAndSaveImage(url));
        const localImagePaths = await Promise.all(downloadPromises); // localImagePaths 中可能包含 null

        // 过滤掉下载失败的图片
        const successfulDownloads = localImagePaths.filter(p => p !== null);
        if (successfulDownloads.length > 0) {
            coverImageLocalPath = successfulDownloads[0]; // 使用第一张成功下载的图片作为封面
        }

        let imageIndex = 0;
        finalMarkdownContent = markdownContentWithPlaceholders.replace(imagePlaceholderRegex, () => {
            const localPath = localImagePaths[imageIndex];
            const imageAltText = imagePrompts[imageIndex];
            imageIndex++;
            // 如果图片下载失败，就在文章中移除这个图片标签
            if (localPath === null) {
                logger.warn(`Image for prompt "${imageAltText}" failed to download. It will be removed from the article.`);
                return ''; 
            }
            return `![${imageAltText}](${localPath})`;
        });
        logger.info("图片处理完成。");

    } else {
        logger.warn("未在文章中找到图片指令，将只生成封面图。");
        const externalUrl = imageService.getImageUrl(`Concept art for "${topic}"`);
        coverImageLocalPath = await imageService.downloadAndSaveImage(externalUrl);
    }
    
    // 如果所有图片都下载失败，提供一个默认的占位图或空值
    if (!coverImageLocalPath) {
        logger.error("所有图片均下载失败，文章将没有封面图。");
        // coverImageLocalPath = '/images/placeholder.jpg'; // 可选：指向一个本地的默认占位图
    }
    
    const title = finalMarkdownContent.split('\n')[0].replace(/#/g, '').trim();
    generationLog.finalMarkdown = finalMarkdownContent;
    
    logger.log('generation', { message: 'Article generation details', ...generationLog });

    const newArticle = {
        id: uuidv4(),
        topic,
        title,
        markdownContent: finalMarkdownContent,
        imageUrl: coverImageLocalPath,
        status: '本地草稿 (Not Pushed)',
        wechatMediaId: 'N/A',
        createdAt: new Date().toISOString(),
    };
    
    return newArticle;
}

// --- 获取文章列表 (保持不变) ---
const getArticles = async (req, res) => {
    try {
        const db = await readDb();
        res.status(200).json(db.articles.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)));
    } catch (error) {
        logger.error('获取文章列表失败:', error);
        res.status(500).json({ message: "无法读取文章列表: " + error.message });
    }
};

// --- 【核心修改】生成文章的主控制器 ---
const generateArticle = async (req, res) => {
  const { topic, writingStylePrompt, apiKey, pushImmediately } = req.body;
  if (!topic || !writingStylePrompt || !apiKey) {
    return res.status(400).json({ message: '主题、Prompt模板和API Key均不能为空' });
  }

  try {
    logger.info(`收到生成文章请求，主题: "${topic}"`);
    logger.info('--- Stage 1: Planning & Outlining ---');

    const planningPrompt = `
你是一个专业的文章规划师。你的任务是为主题「${topic}」做一份创作规划。
在规划时，你必须严格遵循下方“作者风格指南”中定义的人设、风格和所有要求。

--- 作者风格指南 ---
${writingStylePrompt}
--- 结束风格指南 ---

请严格按照下面的格式返回你的规划，用特殊标记分隔每个部分，不要有任何多余的文字。

[ANGLE]
在这里写一句话定义文章的核心情感切入点。
[END_ANGLE]

[GOLDEN_SENTENCE]
在这里写一句原创的、深刻的、能作为文章龙骨的核心金句。
[END_GOLDEN_SENTENCE]

[OUTLINE]
# 在这里写文章总标题
## 一、第一个小标题
## 二、第二个小标题
...
[END_OUTLINE]
`;

    const planningResponseText = await llmService.generateText(planningPrompt, apiKey);
    let plan = {};
    
    try {
        const angleMatch = planningResponseText.match(/\[ANGLE\]([\s\S]*?)\[END_ANGLE\]/);
        const sentenceMatch = planningResponseText.match(/\[GOLDEN_SENTENCE\]([\s\S]*?)\[END_GOLDEN_SENTENCE\]/);
        const outlineMatch = planningResponseText.match(/\[OUTLINE\]([\s\S]*?)\[END_OUTLINE\]/);

        if (!outlineMatch) {
            throw new Error("AI响应中未能解析出[OUTLINE]部分。");
        }

        plan = {
            angle: angleMatch ? angleMatch[1].trim() : '',
            golden_sentence: sentenceMatch ? sentenceMatch[1].trim() : '',
            outline: outlineMatch[1].trim(),
        };
        logger.info('成功解析AI生成的文章规划。');
        logger.debug(plan);
    } catch(e) {
        logger.error('解析AI规划失败，将使用原始文本作为大纲。', { error: e.message, response: planningResponseText });
        plan = { outline: `请围绕主题「${topic}」进行创作。`, angle: '', golden_sentence: '' };
    }

    logger.info('--- Stage 2: Writing Execution ---');
    
    // 第2步：AI执行写作。
    const finalWritingPrompt = `
# 写作总指令
你的任务是撰写一篇完整的文章。在写作过程中，你必须严格遵守以下两个核心部分的内容：【作者风格指南】和【写作大纲】。

--- 作者风格指南 ---
${writingStylePrompt.replace(/{{topic}}/g, topic)}
--- 结束风格指南 ---

--- 写作大纲 ---
${plan.outline}
--- 结束大纲 ---

# 额外要求
请在文章中，自然地融入以下由你之前规划好的核心元素：
- 核心情感角度: "${plan.angle}"
- 核心金句参考: "${plan.golden_sentence}"

现在，请开始你的创作。
`;
    
    logger.info('--- Final Prompt Sent to LLM API (Writing Stage) ---');
    logger.info(`\n${finalWritingPrompt}`);
    logger.info('------------------------------------');

    const articleText = await llmService.generateText(finalWritingPrompt, apiKey); 
    let savedArticle = await _processAndSaveArticle(topic, articleText);

    if (pushImmediately) {
        logger.info(`正在为文章 [${savedArticle.title}] 立即推送到微信...`);
        const wechatResult = await wechatService.pushToWechat(savedArticle.title, savedArticle.markdownContent, savedArticle.imageUrl);
        savedArticle.status = wechatResult.errmsg || 'Pushed to Draft';
        savedArticle.wechatMediaId = wechatResult.media_id || 'N/A';
        logger.info(`文章 [${savedArticle.title}] 推送成功, 微信草稿ID: ${savedArticle.wechatMediaId}`);
    }
    
    const db = await readDb();
    db.articles.push(savedArticle);
    await writeDb(db);
    logger.info(`文章 [${savedArticle.title}] 已成功保存到本地数据库。`);

    res.status(201).json({ message: '文章处理流程完成!', article: savedArticle });
  } catch (error) {
    logger.error(`生成文章流程出错: ${error.message}`, { stack: error.stack });
    res.status(500).json({ message: error.message });
  }
};

// --- 其他控制器函数 (保持不变) ---
const pushArticleById = async (req, res) => {
    const { id } = req.params;
    try {
        const db = await readDb();
        const articleIndex = db.articles.findIndex(art => art.id === id);
        if (articleIndex === -1) return res.status(404).json({ message: '未找到该文章' });
        const articleToPush = db.articles[articleIndex];
        if (articleToPush.status === 'Pushed to Draft') return res.status(400).json({ message: '该文章已经被推送，请勿重复操作' });
        logger.info(`收到手动推送请求，文章: [${articleToPush.title}]`);
        const wechatResult = await wechatService.pushToWechat(articleToPush.title, articleToPush.markdownContent, articleToPush.imageUrl);
        articleToPush.status = wechatResult.errmsg || 'Pushed to Draft';
        articleToPush.wechatMediaId = wechatResult.media_id || 'N/A';
        db.articles[articleIndex] = articleToPush;
        await writeDb(db);
        logger.info(`文章 [${articleToPush.title}] 手动推送成功, 微信草稿ID: ${articleToPush.wechatMediaId}`);
        res.status(200).json({ message: '文章推送成功!', article: articleToPush });
    } catch (error) {
        logger.error(`推送文章 (ID: ${id}) 出错: ${error.message}`, { stack: error.stack });
        res.status(500).json({ message: error.message });
    }
};

const updateArticleById = async (req, res) => {
    const { id } = req.params;
    const { markdownContent } = req.body;
    if (!markdownContent) return res.status(400).json({ message: '更新内容不能为空' });
    try {
        const db = await readDb();
        const articleIndex = db.articles.findIndex(art => art.id === id);
        if (articleIndex === -1) return res.status(404).json({ message: '未找到该文章' });
        const articleToUpdate = db.articles[articleIndex];
        articleToUpdate.markdownContent = markdownContent;
        const title = markdownContent.split('\n')[0].replace(/#/g, '').trim();
        articleToUpdate.title = title;
        const imageMatch = markdownContent.match(/!\[.*?\]\((.*?)\)/);
        if (imageMatch && imageMatch[1]) {
            articleToUpdate.imageUrl = imageMatch[1];
        }
        db.articles[articleIndex] = articleToUpdate;
        await writeDb(db);
        res.status(200).json({ message: '文章保存成功!', article: articleToUpdate });
    } catch (error) {
        logger.error(`更新文章 (ID: ${id}) 出错:`, error);
        res.status(500).json({ message: error.message });
    }
};

/**
 * 【新增】删除文章的控制器
 */
const deleteArticleById = async (req, res) => {
    const { id } = req.params;
    try {
        const db = await readDb();
        const articleToDelete = db.articles.find(art => art.id === id);

        if (!articleToDelete) {
            return res.status(404).json({ message: '未找到要删除的文章' });
        }

        // 从文章内容中解析出所有本地图片路径
        const imagePaths = (articleToDelete.markdownContent.match(/\/images\/[a-f0-9-]+\.jpg/g) || []);
        
        // 删除关联的图片文件
        if (imagePaths.length > 0) {
            logger.info(`准备删除文章 [${articleToDelete.title}] 关联的 ${imagePaths.length} 张图片...`);
            for (const localPath of imagePaths) {
                const fullPath = path.join(__dirname, '..', 'public', localPath);
                try {
                    await fs.unlink(fullPath);
                    logger.info(`已删除图片: ${fullPath}`);
                } catch (err) {
                    // 如果文件不存在或其他错误，只记录日志，不中断流程
                    logger.error(`删除图片失败: ${fullPath}`, err);
                }
            }
        }
        
        // 从数据库中过滤掉该文章
        db.articles = db.articles.filter(art => art.id !== id);
        await writeDb(db);
        
        logger.info(`文章 [${articleToDelete.title}] 已成功从数据库删除。`);
        res.status(200).json({ message: '文章及关联图片已成功删除' });

    } catch (error) {
        logger.error(`删除文章 (ID: ${id}) 出错:`, error);
        res.status(500).json({ message: '删除文章失败' });
    }
};

module.exports = { getArticles, generateArticle, pushArticleById, updateArticleById,deleteArticleById };